home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / machine / mathbox.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  7KB  |  278 lines

  1. /*
  2.  * mathbox.c: math box simulation (Battlezone/Red Baron/Tempest)
  3.  *
  4.  * Copyright 1991, 1992, 1993, 1996 Eric Smith
  5.  *
  6.  * $Header: /usr2/eric/vg/atari/vecsim/RCS/mathbox.c,v 1.1 1996/08/29 07:23:59 eric Exp eric $
  7.  */
  8.  
  9. #include "driver.h"
  10. #include "mathbox.h"
  11.  
  12. /* math box scratch registers */
  13. s16 mb_reg [16];
  14.  
  15. /* math box result */
  16. s16 mb_result = 0;
  17.  
  18. #define REG0 mb_reg [0x00]
  19. #define REG1 mb_reg [0x01]
  20. #define REG2 mb_reg [0x02]
  21. #define REG3 mb_reg [0x03]
  22. #define REG4 mb_reg [0x04]
  23. #define REG5 mb_reg [0x05]
  24. #define REG6 mb_reg [0x06]
  25. #define REG7 mb_reg [0x07]
  26. #define REG8 mb_reg [0x08]
  27. #define REG9 mb_reg [0x09]
  28. #define REGa mb_reg [0x0a]
  29. #define REGb mb_reg [0x0b]
  30. #define REGc mb_reg [0x0c]
  31. #define REGd mb_reg [0x0d]
  32. #define REGe mb_reg [0x0e]
  33. #define REGf mb_reg [0x0f]
  34.  
  35.  
  36. /*define MB_TEST*/
  37.  
  38. WRITE_HANDLER( mb_go_w )
  39. {
  40.   s32 mb_temp;  /* temp 32-bit multiply results */
  41.   s16 mb_q;     /* temp used in division */
  42.   int msb;
  43.  
  44. #ifdef MB_TEST
  45.   logerror("math box command %02x data %02x  ", offset, data);
  46. #endif
  47.  
  48.   switch (offset)
  49.     {
  50.     case 0x00: mb_result = REG0 = (REG0 & 0xff00) | data;        break;
  51.     case 0x01: mb_result = REG0 = (REG0 & 0x00ff) | (data << 8); break;
  52.     case 0x02: mb_result = REG1 = (REG1 & 0xff00) | data;        break;
  53.     case 0x03: mb_result = REG1 = (REG1 & 0x00ff) | (data << 8); break;
  54.     case 0x04: mb_result = REG2 = (REG2 & 0xff00) | data;        break;
  55.     case 0x05: mb_result = REG2 = (REG2 & 0x00ff) | (data << 8); break;
  56.     case 0x06: mb_result = REG3 = (REG3 & 0xff00) | data;        break;
  57.     case 0x07: mb_result = REG3 = (REG3 & 0x00ff) | (data << 8); break;
  58.     case 0x08: mb_result = REG4 = (REG4 & 0xff00) | data;        break;
  59.     case 0x09: mb_result = REG4 = (REG4 & 0x00ff) | (data << 8); break;
  60.  
  61.     case 0x0a: mb_result = REG5 = (REG5 & 0xff00) | data;        break;
  62.       /* note: no function loads low part of REG5 without performing a computation */
  63.  
  64.     case 0x0c: mb_result = REG6 = data; break;
  65.       /* note: no function loads high part of REG6 */
  66.  
  67.     case 0x15: mb_result = REG7 = (REG7 & 0xff00) | data;        break;
  68.     case 0x16: mb_result = REG7 = (REG7 & 0x00ff) | (data << 8); break;
  69.  
  70.     case 0x1a: mb_result = REG8 = (REG8 & 0xff00) | data;        break;
  71.     case 0x1b: mb_result = REG8 = (REG8 & 0x00ff) | (data << 8); break;
  72.  
  73.     case 0x0d: mb_result = REGa = (REGa & 0xff00) | data;        break;
  74.     case 0x0e: mb_result = REGa = (REGa & 0x00ff) | (data << 8); break;
  75.     case 0x0f: mb_result = REGb = (REGb & 0xff00) | data;        break;
  76.     case 0x10: mb_result = REGb = (REGb & 0x00ff) | (data << 8); break;
  77.  
  78.     case 0x17: mb_result = REG7; break;
  79.     case 0x19: mb_result = REG8; break;
  80.     case 0x18: mb_result = REG9; break;
  81.  
  82.     case 0x0b:
  83.  
  84.       REG5 = (REG5 & 0x00ff) | (data << 8);
  85.  
  86.       REGf = (s16)0xffff;
  87.       REG4 -= REG2;
  88.       REG5 -= REG3;
  89.  
  90.     step_048:
  91.  
  92.       mb_temp = ((s32) REG0) * ((s32) REG4);
  93.       REGc = mb_temp >> 16;
  94.       REGe = mb_temp & 0xffff;
  95.  
  96.       mb_temp = ((s32) -REG1) * ((s32) REG5);
  97.       REG7 = mb_temp >> 16;
  98.       mb_q = mb_temp & 0xffff;
  99.  
  100.       REG7 += REGc;
  101.  
  102.       /* rounding */
  103.       REGe = (REGe >> 1) & 0x7fff;
  104.       REGc = (mb_q >> 1) & 0x7fff;
  105.       mb_q = REGc + REGe;
  106.       if (mb_q < 0)
  107.     REG7++;
  108.  
  109.       mb_result = REG7;
  110.  
  111.       if (REGf < 0)
  112.     break;
  113.  
  114.       REG7 += REG2;
  115.  
  116.       /* fall into command 12 */
  117.  
  118.     case 0x12:
  119.  
  120.       mb_temp = ((s32) REG1) * ((s32) REG4);
  121.       REGc = mb_temp >> 16;
  122.       REG9 = mb_temp & 0xffff;
  123.  
  124.       mb_temp = ((s32) REG0) * ((s32) REG5);
  125.       REG8 = mb_temp >> 16;
  126.       mb_q = mb_temp & 0xffff;
  127.  
  128.       REG8 += REGc;
  129.  
  130.       /* rounding */
  131.       REG9 = (REG9 >> 1) & 0x7fff;
  132.       REGc = (mb_q >> 1) & 0x7fff;
  133.       REG9 += REGc;
  134.       if (REG9 < 0)
  135.     REG8++;
  136.       REG9 <<= 1;  /* why? only to get the desired load address? */
  137.  
  138.       mb_result = REG8;
  139.  
  140.       if (REGf < 0)
  141.     break;
  142.  
  143.       REG8 += REG3;
  144.  
  145.       REG9 &= 0xff00;
  146.  
  147.       /* fall into command 13 */
  148.  
  149.     case 0x13:
  150. #ifdef MB_TEST
  151.       logerror("\nR7: %04x  R8: %04x  R9: %04x\n", REG7, REG8, REG9);
  152. #endif
  153.  
  154.       REGc = REG9;
  155.       mb_q = REG8;
  156.       goto step_0bf;
  157.  
  158.     case 0x14:
  159.       REGc = REGa;
  160.       mb_q = REGb;
  161.  
  162.     step_0bf:
  163.       REGe = REG7 ^ mb_q;  /* save sign of result */
  164.       REGd = mb_q;
  165.       if (mb_q >= 0)
  166.     mb_q = REGc;
  167.       else
  168.     {
  169.       REGd = - mb_q - 1;
  170.       mb_q = - REGc - 1;
  171.       if ((mb_q < 0) && ((mb_q + 1) < 0))
  172.         REGd++;
  173.       mb_q++;
  174.     }
  175.  
  176.     /* step 0c9: */
  177.       /* REGc = abs (REG7) */
  178.       if (REG7 >= 0)
  179.     REGc = REG7;
  180.       else
  181.         REGc = -REG7;
  182.  
  183.       REGf = REG6;  /* step counter */
  184.  
  185.       do
  186.     {
  187.       REGd -= REGc;
  188.       msb = ((mb_q & 0x8000) != 0);
  189.       mb_q <<= 1;
  190.       if (REGd >= 0)
  191.         mb_q++;
  192.       else
  193.         REGd += REGc;
  194.       REGd <<= 1;
  195.       REGd += msb;
  196.     }
  197.       while (--REGf >= 0);
  198.  
  199.       if (REGe >= 0)
  200.     mb_result = mb_q;
  201.       else
  202.     mb_result = - mb_q;
  203.       break;
  204.  
  205.     case 0x11:
  206.       REG5 = (REG5 & 0x00ff) | (data << 8);
  207.       REGf = 0x0000;  /* do everything in one step */
  208.       goto step_048;
  209.       break;
  210.  
  211.     case 0x1c:
  212.       /* window test? */
  213.       REG5 = (REG5 & 0x00ff) | (data << 8);
  214.       do
  215.     {
  216.       REGe = (REG4 + REG7) >> 1;
  217.       REGf = (REG5 + REG8) >> 1;
  218.       if ((REGb < REGe) && (REGf < REGe) && ((REGe + REGf) >= 0))
  219.         { REG7 = REGe; REG8 = REGf; }
  220.       else
  221.         { REG4 = REGe; REG5 = REGf; }
  222.     }
  223.       while (--REG6 >= 0);
  224.  
  225.       mb_result = REG8;
  226.       break;
  227.  
  228.     case 0x1d:
  229.       REG3 = (REG3 & 0x00ff) | (data << 8);
  230.  
  231.       REG2 -= REG0;
  232.       if (REG2 < 0)
  233.     REG2 = -REG2;
  234.  
  235.       REG3 -= REG1;
  236.       if (REG3 < 0)
  237.     REG3 = -REG3;
  238.  
  239.       /* fall into command 1e */
  240.  
  241.     case 0x1e:
  242.       /* result = max (REG2, REG3) + 3/8 * min (REG2, REG3) */
  243.       if (REG3 >= REG2)
  244.         { REGc = REG2; REGd = REG3; }
  245.       else
  246.     { REGd = REG2; REGc = REG3; }
  247.       REGc >>= 2;
  248.       REGd += REGc;
  249.       REGc >>= 1;
  250.       mb_result = REGd = (REGc + REGd);
  251.       break;
  252.  
  253.     case 0x1f:
  254.       logerror("math box function 0x1f\n");
  255.       /* $$$ do some computation here (selftest? signature analysis? */
  256.       break;
  257.     }
  258.  
  259. #ifdef MB_TEST
  260.   logerror("  result %04x\n", mb_result & 0xffff);
  261. #endif
  262. }
  263.  
  264. READ_HANDLER( mb_status_r )
  265. {
  266.     return 0x00; /* always done! */
  267. }
  268.  
  269. READ_HANDLER( mb_lo_r )
  270. {
  271.     return mb_result & 0xff;
  272. }
  273.  
  274. READ_HANDLER( mb_hi_r )
  275. {
  276.     return (mb_result >> 8) & 0xff;
  277. }
  278.